"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 硬件故障类--磁盘
Case Name   : 硬盘数据错误
Create At   : 2020-12-29
Owner       : n@ningyali
Description :
    1、DN主注入故障
        ./cfe "inject rdisk(fault,dev,ms,freq,count,lba,endlba)values(icrc,/dev/sdb,100000,100,400,0,0xFFFF)"
    2、查询故障是否注入成功
        ./cfe "query  rdisk "
    3、对数据库进行启停、登录等操作
    4、清除故障
        ./cfe "clean  rdisk"
    5、对数据库进行启停、登录等操作
Expect      :
    1、故障注入成功
    2、IO阻塞，数据库启停失败、连接失败
    3、清除故障成功
    4、数据库恢复正常
History     :
"""

import unittest

from yat.test import Node
from yat.test import macro

from testcase.utils.Common import *
from testcase.utils.CommonSH import *


class PrimaryNodeInjectIcrc(unittest.TestCase):
    primary_sh = CommonSH('PrimaryDbUser')
    standby1_sh = CommonSH('Standby1DbUser')
    standby2_sh = CommonSH('Standby2DbUser')
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.log = Logger()
        self.log.info('------------Opengauss_Reliability_Hardware_Case020:开始执行------------')
        self.primary_root_node = Node(node='PrimaryRoot')
        self.primary_user_node = Node(node='PrimaryDbUser')
        self.com = Common()
        self.Constant = Constant()
        self.t_name = 'test_hardware020'

        self.log.info("---------------获取DN主磁盘名----------------")
        shell_cmd = f"df -h {macro.DB_INSTANCE_PATH}"
        self.log.info(shell_cmd)
        result = self.primary_root_node.sh(shell_cmd).result()
        self.disk_name = result.splitlines()[-1].split()[0].strip()
        self.log.info('result: ' + result + '\n' + 'disk_name: ' + self.disk_name)

    def test_main(self):
        self.log.info("---------------获取起始时间----------------")
        shell_cmd = 'date +"%Y-%m-%d %H:%M:%S"'
        self.log.info(shell_cmd)
        start_time = self.primary_root_node.sh(shell_cmd).result()

        self.log.info("---------------获取磁盘扇区个数----------------")
        shell_cmd = f"fdisk -l {self.disk_name}"
        self.log.info(shell_cmd)
        msg = self.primary_root_node.sh(shell_cmd).result()
        sectors = msg.splitlines()[0].split(',')[-1].split()[0].strip()
        self.log.info('result: ' + msg + '\n' + 'sectors: ' + sectors)

        self.log.info("---------------DN主注入故障----------------")
        endlba = len(hex(int(sectors))) * 'F'
        shell_cmd = f'''{macro.CFE_PATH}/cfe 'inject rdisk(fault,dev,ms,freq,count,lba,endlba)values(icrc,{self.disk_name},60000,10,6000,0,0x{endlba})' '''
        self.log.info(shell_cmd)
        msg = self.primary_root_node.sh(shell_cmd).result()
        self.log.info(msg)
        self.assertIn(self.Constant.CFE_INJECT_RDISK_SUCCESS_MSG, msg)

        self.log.info("-------------查询故障是否注入成功---------------")
        shell_cmd = f'''{macro.CFE_PATH}/cfe 'query  rdisk' | grep {self.disk_name} | grep icrc '''
        self.log.info(shell_cmd)
        msg = self.primary_root_node.sh(shell_cmd).result()
        self.log.info(msg)
        self.assertTrue(len(msg) > 0)

        self.log.info("-------------查看集群状态---------------")
        db_status = self.primary_sh.getDbClusterStatus('detail')
        self.log.info(db_status)

        self.log.info("-------------对数据库进行启停、登录等操作---------------")
        msg = self.primary_sh.executDbSql(r'\l')
        self.log.info(msg)

        is_stopped = self.primary_sh.stopDbCluster(max_time='300')
        self.log.info(is_stopped)

        is_started = self.primary_sh.startDbCluster()
        self.log.info(is_started)

        self.log.info("---------------清除故障----------------")
        shell_cmd = f'''{macro.CFE_PATH}/cfe 'clean  rdisk' '''
        self.log.info(shell_cmd)
        msg = self.primary_root_node.sh(shell_cmd).result()
        self.log.info(msg)
        self.assertIn(self.Constant.CFE_CLEAN_RDISK_SUCCESS_MSG, msg)

        self.log.info("--------------可能需要reboot--------------")
        shell_cmd = "reboot"
        self.log.info(shell_cmd)
        self.primary_root_node.sh(shell_cmd)

        for i in range(30):
            time.sleep(60)
            is_started = self.standby1_sh.startDbCluster()
            if is_started:
                self.log.info('reboot后启动成功')
                break

        self.log.info("-------------reboot后需重开session---------------")
        self.primary_sh = CommonSH('PrimaryDbUser')
        self.primary_root_node = Node(node='PrimaryRoot')

        self.log.info("-------------查看集群状态---------------")
        db_status = self.primary_sh.getDbClusterStatus('status')
        self.assertTrue(db_status)

        self.log.info("---------------获取结束时间----------------")
        shell_cmd = 'date +"%Y-%m-%d %H:%M:%S"'
        self.log.info(shell_cmd)
        end_time = self.primary_root_node.sh(shell_cmd).result()

        self.log.info("---------------查看时间段内生成的pg_log，有相应的提示信息----------------")
        shell_cmd = f"find {os.path.join(macro.PG_LOG_PATH, macro.DN_NODE_NAME.split('/')[0])} " \
            f"-type f -newermt '{start_time}' ! -newermt '{end_time}' | xargs grep -r 'Input/output error' -n"
        self.log.info(shell_cmd)
        msg = self.primary_root_node.sh(shell_cmd).result()
        self.log.info(msg)
        self.assertTrue(len(msg) > 0)

        self.log.info("-------------对数据库进行启停、登录等操作---------------")
        msg = self.primary_sh.executDbSql(r'\l')
        self.log.info(msg)

        is_stopped = self.primary_sh.stopDbCluster()
        self.assertTrue(is_stopped)

        is_started = self.primary_sh.startDbCluster()
        self.assertTrue(is_started)

        self.log.info("-------------查看集群状态---------------")
        db_status = self.primary_sh.getDbClusterStatus('status')
        self.assertTrue(db_status)

    def tearDown(self):
        self.log.info("---------------清除故障----------------")
        shell_cmd = f'''{macro.CFE_PATH}/cfe 'clean  rdisk' '''
        self.log.info(shell_cmd)
        msg = self.primary_root_node.sh(shell_cmd).result()
        self.log.info(msg)
        self.log.info('------------Opengauss_Reliability_Hardware_Case020:执行完成------------')
